from odoo import fields, models, api
from odoo.exceptions import UserError
from lxml import etree

AGREEMENT_TYPE = [('terms_and_condition', '条款和条件'), ('cookie_policy', 'Cookie政策'), ('legal_notice', '合法通知'), ('prohibited_goods', '禁止货物')]
AGREEMENT_STATE = [('create', '创建'), ('enable', '启用'), ('publish', '发布'), ('deprecation', '下架'), ('disable', '弃用')]
NAVIGATION_LEVEL = [('head_one', '一级'), ('head_two', '二级'), ('head_three', '三级')]


class RpComplianceAndUserAgreements(models.Model):
    _name = 'rp.compliance.and.user.agreements'
    _description = '条规和用户协议'
    _sql_constraints = [('unique_name', 'UNIQUE(code)', '索引码需要唯一')]
    _rec_name = 'code'

    code = fields.Char(string='序列号', default='RP_CA/****', readonly=True, copy=False, index=True)
    author = fields.Many2one(string='作者', comodel_name='res.users', default=lambda self: self.env.user)
    type = fields.Selection(string='类型', selection=AGREEMENT_TYPE, required=True)

    # 时间相关
    create_time = fields.Datetime(string='创建时间', default=fields.Datetime.now, copy=False, index=True)
    publish_time = fields.Datetime(string='发布时间', copy=False, index=True)
    deprecation_time = fields.Datetime(string='下架时间', copy=False, index=True)
    disable_time = fields.Datetime(string='弃用时间', copy=False, index=True)

    # 文本内容
    title = fields.Char(string='标题', translate=True, required=True)
    sub_title = fields.Char(string='副标题', translate=True, required=True)
    introduction = fields.Text(string='简介')
    body = fields.Html(string='内容')
    navigation_ids = fields.One2many(string='目录', comodel_name='rp.compliance.and.user.agreements.navigation.line', inverse_name='compliance_and_agreement_id', store=True)
    publish_flag = fields.Boolean(string='发布', default=False, copy=False)

    state = fields.Selection(string='状态', selection=AGREEMENT_STATE, default=AGREEMENT_STATE[0][0])

    """
    Native Function
    """

    @api.model_create_single
    def create(self, vals):
        data_dict = {'code': self.env['ir.sequence'].next_by_code('rp.compliance.and.user.agreements') or '/'}
        vals.update(data_dict)
        return super(RpComplianceAndUserAgreements, self).create(vals)

    """
    Button Function
    """

    def turn_publish(self):
        """
        发布【弃用先启用再发布】【下架状态的仍是启用，只不过下架了】
        """
        origin_state = self.state
        if origin_state in ['create', 'disable']:
            raise UserError(f'目前状态为【{origin_state}】,需要先启用后再发布！')
        if origin_state == 'publish':
            raise UserError('状态已经为已发布！')
        self.write({'state': 'publish', 'publish_time': fields.Datetime.now(), 'publish_flag': True})

    def turn_deprecation(self):
        """
        下架【已发布才可以下架】
        """
        origin_state = self.state
        if origin_state != 'publish':
            raise UserError('只有已发布才可以下架！')
        if origin_state == 'deprecation':
            raise UserError('状态已经为下架状态！')
        self.write({'state': 'deprecation', 'deprecation_time': fields.Datetime.now()})

    def turn_disable(self):
        """
        弃用【只有创建，弃用状态不可弃用】
        """
        origin_state = self.state
        if origin_state == 'disable':
            raise UserError('状态已经为弃用状态！')
        self.write({'state': 'disable', 'disable_time': fields.Datetime.now()})

    def turn_enable(self):
        """
        启用【弃用状态才可以启用】
        """
        origin_state = self.state
        if origin_state != 'disable':
            raise UserError(f'状态【({origin_state})】不可弃用！')
        if origin_state == 'enable':
            raise UserError('状态已经为启用状态！')
        self.write({'state': 'enable'})

    def generator_navigation_lines(self):

        body_str = str(self.body)
        tree_obj = etree.HTML(body_str)
        # 查看富文本是否包含有效内容，而不是空标签
        text_tag = tree_obj.xpath('//*[normalize-space(text())]')
        if text_tag:
            # 获取对应的标题
            h1_list = tree_obj.xpath('//h1')
            for h1 in h1_list:
                h1_text = h1.text.strip()
                values = {
                    'name': h1_text,
                    'level': NAVIGATION_LEVEL[0][0],
                    'compliance_and_agreement_id': self.id,
                    'is_root': True
                }
                # 创建记录
                existed_id = self.env['rp.compliance.and.user.agreements.navigation.line'].search([('name', '=', h1.text.strip()), ('level', '=', NAVIGATION_LEVEL[0][0]), ('compliance_and_agreement_id', '=', self.id), ('is_root', '=', True)])
                if not existed_id:
                    self.env['rp.compliance.and.user.agreements.navigation.line'].create(values)
            h2_list = tree_obj.xpath('//h2')
            if len(h2_list) > 0:
                for record in h2_list:
                    # 只有标签没有文本跳过
                    if record.text is None:
                        continue
                    # 获取记录该h1标签最近的h1标签
                    nearly_h1 = record.xpath('preceding::h1[1]')[0]
                    parent_id = self.env['rp.compliance.and.user.agreements.navigation.line'].search([('name', '=', nearly_h1.text.strip()), ('compliance_and_agreement_id', '=', self.id)])
                    values = {
                        'name': record.text.strip(),
                        'level': NAVIGATION_LEVEL[1][0],
                        'compliance_and_agreement_id': self.id,
                        'parent_navigation_id': parent_id.id,
                        'is_root': False
                    }
                    existed_id = self.env['rp.compliance.and.user.agreements.navigation.line'].search([('name', '=', record.text.strip()), ('level', '=', NAVIGATION_LEVEL[1][0]), ('compliance_and_agreement_id', '=', self.id), ('is_root', '=', False)])
                    if not existed_id:
                        self.env['rp.compliance.and.user.agreements.navigation.line'].create(values)
                    else:
                        existed_id.write({'parent_navigation_id': parent_id.id})
            h3_list = tree_obj.xpath('//h3')
            if len(h2_list) > 0 and len(h3_list) > 0:
                for record in h3_list:
                    if record.text is None:
                        continue
                    # 获取记录该h2标签最近的h2标签
                    nearly_h2 = record.xpath('preceding::h2[1]')[0]
                    parent_id = self.env['rp.compliance.and.user.agreements.navigation.line'].search([('name', '=', nearly_h2.text.strip()), ('compliance_and_agreement_id', '=', self.id)])
                    values = {
                        'name': record.text.strip(),
                        'level': NAVIGATION_LEVEL[2][0],
                        'compliance_and_agreement_id': self.id,
                        'parent_navigation_id': parent_id.id,
                        'is_root': False
                    }
                    existed_id = self.env['rp.compliance.and.user.agreements.navigation.line'].search([('name', '=', record.text.strip()), ('level', '=', NAVIGATION_LEVEL[2][0]), ('compliance_and_agreement_id', '=', self.id), ('is_root', '=', False)])
                    if not existed_id:
                        self.env['rp.compliance.and.user.agreements.navigation.line'].create(values)
                    else:
                        # 更新父级ID
                        existed_id.write({'parent_navigation_id': parent_id.id})
        else:
            navigation_ids = self.navigation_ids
            # 清除关系
            self.write({'navigation_ids': [(5, 0, 0)]})
            # 删除数据
            if navigation_ids:
                navigation_ids.unlink()
            # 重置ID值
            cr = self.env.cr  # 获取游标
            cr.execute("select setval('rp_compliance_and_user_agreements_navigation_line_id_seq',(select max(id) from rp_compliance_and_user_agreements_navigation_line));")
            # 提交事务
            self.env.cr.commit()


class RpComplianceAndUserAgreementsNavigationLine(models.Model):
    _name = 'rp.compliance.and.user.agreements.navigation.line'
    _description = '条规和用户协议目录'

    name = fields.Char(string='名称')
    level = fields.Selection(string='级别', selection=NAVIGATION_LEVEL)
    compliance_and_agreement_id = fields.Many2one(string='关联主表', comodel_name='rp.compliance.and.user.agreements', ondelete='cascade')
    parent_navigation_id = fields.Many2one(string='上级目录', comodel_name='rp.compliance.and.user.agreements.navigation.line')
    is_root = fields.Boolean(string='是否为根层级', default=False)
    active_flag = fields.Boolean(string='有效', default=True)
